﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using API;
using AVFoundation;
using AVKit;
using CoreFoundation;
using CoreGraphics;
using Foundation;
using mb;
using mb.iOS;
using Masonry;
using MyExtensions;
using UIKit;
using static libmp.DataStore;
using System.Collections.Generic;

namespace libmp
{
    //最基础的列表类，主要目的是把MyCollectionView里的一堆回调转成虚函数
    abstract class VCBaseList : UIViewController
    {
        static protected ILog logger = mb.ServiceLocator.Instance.Get<ILog>();
        List<DataStore.VideoItem> allVideo = DataStore.store.GetAllVideo();
        List<DataStore.VideoItem> recommendVideo;
        protected MyCollectionView listView;
        public VCBaseList() : base()
        {
            logger.Log("vcbaselist ctor");
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            CreateList();
            listView.SetParent(View);

            listView.MakeConstraints(m =>
            {
                m.Left.Right.EqualTo(View);
                m.Top.EqualTo(this.TopLayoutGuideBottom());
                m.Bottom.EqualTo(this.BottomLayoutGuideTop());
            });
        }

        public MyCollectionView GetView() => listView as MyCollectionView;

        protected class CellData
        {
            public UILabel label;
        };
        CellData InitRecommmendVideoCell(MyCollectionViewCell cell)
        {
            var cd = new CellData();
            cell.data = cd;
            return cd;
        }

        protected abstract int GetSectionCount();
        protected abstract int GetItemsCount(int sec);
        protected abstract CGSize GetItemsSize(int sec, int idx);
        protected virtual void OnScrolled() { }
        protected virtual void OnItemSelected(int sec, int idx) { }
        protected virtual void InitCell(MyCollectionViewCell cell, int sec) { }
        protected virtual void UpdateCell(MyCollectionViewCell cell, int sec, int idx) { }

        MyCollectionView CreateList()
        {
            listView = new MyCollectionView(GetSectionCount())
            {
                BackgroundColor = View.BackgroundColor,
                    MyScrolled = (v) =>
                    {
                        OnScrolled();
                    },
                    MyItemSelected = async(v, ip) =>
                    {
                        OnItemSelected(ip.Section, (int) ip.Item);
                    },
                    MyGetItemsCount = (v, sec) => GetItemsCount(sec),

                    MyGetCell = (v, ip) =>
                    {
                        var cell = v.DequeueReusableCell("Cell" + ip.Section, ip) as MyCollectionViewCell;
                        if (cell.data == null)
                            InitCell(cell, ip.Section);

                        UpdateCell(cell, ip.Section, (int) ip.Item);
                        return cell;
                    },
                    MyGetMinimumLineSpacingForSection = (v, layout, sec) => 1,
                    MyGetInsetForSection = (v, layout, sec) =>
                    {
                        var dd = 0;
                        return new UIEdgeInsets(dd, dd, dd, dd);
                    },
                    MyGetSizeForItem = (v, layout, ip) => GetItemsSize(ip.Section, (int) ip.Item),
            };

            return listView;

        }
    }

    //在固定数据列表中插入其它视图，自动计算插入后的分段
    class VCBaseInsertableList<T> : VCBaseList
    {
        protected List<T> dataSource { set; get; }

        protected virtual int[] GetInsertIndex() { return new int[0]; }
        protected virtual UIView GetInsertView(int idx, MyCollectionViewCell parent) { return null; }
        protected virtual InsertItem GetInsertViewConfig(int idx) { return null; }

        protected class InsertItem
        {
            public UIView view;
            public int insertBefore;
            public int height;
            public int stickyHeight;
            public bool overwrite;
        }

        protected class SectionData
        {
            public int sectionIndex;
            public UIView insertView;
            public int insertViewIndex;
            public int insertViewHeight;
            public int insertViewStickHeight; //吸附高度，0为不吸附，
            public bool insertViewStickOverwrite; //吸附覆盖上一个
            public int dataStartIndex;
            public int dataCount;

            public bool IsInsertView() { return insertViewIndex != -1; }
            public SectionData()
            {
                insertViewIndex = -1;
                insertViewStickHeight = 0;
                insertViewStickOverwrite = false;
                dataStartIndex = -1;
            }
        }
        protected List<SectionData> sections;

        protected class MyCellData : CellData
        {
            public UILabel labTitle;

            public MyCellData(MyCollectionViewCell cell)
            {
                labTitle = new UILabel();
                labTitle.SetParent(cell);
                labTitle.MakeConstraints(m =>
                {
                    m.Edges.EqualTo(cell);
                });
            }
        }
        protected override void OnScrolled()
        {
            UpdateSticky();
        }
        protected void UpdateSticky()
        {
            var ivSections = sections.Where(s => s.IsInsertView());
            var itor = ivSections.GetEnumerator();
            nfloat listViewTop = listView.Frame.Top;
            nfloat keepTop = 0; //粘性对象当前可以对齐的顶部，从0开始，每当有对象已经粘住时，下一个对象从上一个的底部算起
            nfloat keepTopLast = 0;
            SectionData secLast = null;
            while (itor.MoveNext())
            {
                var sec = itor.Current;
                if (sec.insertViewStickHeight == 0) continue;

                var fcp = NSIndexPath.FromItemSection(0, sec.sectionIndex);
                var cell = listView.CellForItem(fcp) as MyCollectionViewCell;
                // if (cell == null) continue;

                CGRect rtBase = listView.GetLayoutAttributesForItem(fcp).Frame;
                CGRect rtNow = listView.ConvertRectToView(rtBase, View);

                //该view相对于list的偏移，往上移出去时为负数
                var offsetY = rtNow.Y - listViewTop;

                //该view相对于对齐顶部，剩余的高度。即自身高度减去在对齐线之上的部份
                var remainHeight = (nfloat) sec.insertViewHeight - (keepTop - offsetY);

                // logger.Log($"iv check, sec:{sec.sectionIndex}, cell:{cell!=null} keeptop:{keepTop} offy:{offsetY} remainh:{remainHeight} overwrite:{sec.insertViewStickOverwrite}");

                //如果剩余高度小于设置的粘性高度，那么不能再随list一起滚，摘下来单独安置
                if (remainHeight < sec.insertViewStickHeight)
                {
                    var top = listViewTop + keepTop;

                    if (cell != null) //避免重复设置，性能及抖动
                    {
                        // if (sec.insertView.Superview != View) //避免重复设置，性能及抖动
                        {
                            sec.insertView.RemoveFromSuperview();
                            sec.insertView.SetParent(View);
                        }
                        sec.insertView.Frame = CGRect.FromLTRB(0, top, cell.Frame.Width, top + sec.insertViewStickHeight);
                        // sec.insertView.Frame = CGRect.FromLTRB(0, 100, 100, 200);
                        // logger.Log($"iv sticky1, sec:{sec.sectionIndex} ", sec.insertView.Frame);
                    }

                    //如果是可覆盖的就不要增加keepTop
                    if (!sec.insertViewStickOverwrite)
                    {
                        keepTopLast = keepTop;
                        keepTop += sec.insertViewStickHeight;
                    }

                }
                else
                {
                    if (cell != null && sec.insertView.Superview != cell) //避免重复设置，性能及抖动
                    {
                        sec.insertView.RemoveFromSuperview();
                        sec.insertView.SetParent(cell);
                    }

                    if (offsetY < keepTop) //如果已经部份不可见，调整view的大小，使其内部控件仍然处于可见区域内
                    {
                        if (cell != null)
                            sec.insertView.Frame = CGRect.FromLTRB(0, keepTop - offsetY, cell.Frame.Width, cell.Frame.Height);
                    }
                    else //还是完全可见的时候，保持原状
                    {
                        if (cell != null)
                            sec.insertView.Frame = CGRect.FromLTRB(0, 0, cell.Frame.Width, cell.Frame.Height);
                    }
                }

                //如果上一条是可覆盖的，把它顶走
                if (secLast?.insertViewStickOverwrite??false)
                {
                    //当前条是否已经『过线』了，即：进入被上一条遮盖的区域
                    var over = keepTop + secLast.insertViewStickHeight - offsetY;
                    if (over > 0)
                    {
                        var frame = secLast.insertView.Frame;
                        var top = listViewTop + keepTop - over;
                        top = (nfloat) Math.Max(listViewTop, top);
                        var newframe = CGRect.FromLTRB(frame.Left, top, frame.Right, top + frame.Height);
                        // logger.Log($"iv adjustlast, sec:{secLast.sectionIndex}  over:{over}", newframe);
                        secLast.insertView.Frame = newframe;

                        var(sd, _) = GetInsertViewCell(0);
                        View.BringSubviewToFront(sd.insertView);
                    }
                }

                secLast = sec;
            }

        }

        protected virtual MyCellData CreateCellData(MyCollectionViewCell cell, SectionData sectionData) => new MyCellData(cell);

        protected override void InitCell(MyCollectionViewCell cell, int sec)
        {
            var sd = sections[sec];
            cell.data = CreateCellData(cell, sd);
            // var type = !sd.IsInsertView() ? "data" : "insert";
            // logger.Log("init cell", type, Util.AddrOfObject(cell));
            if (sd.IsInsertView())
            {
                logger.Log("init cell", sec, sd.insertViewIndex);
                if (sd.insertView == null)
                {
                    sd.insertView = GetInsertView(sd.insertViewIndex, cell);
                }
                sd.insertView.SetParent(cell);
                sd.insertView.Frame = new CGRect(0, 0, cell.Frame.Width, cell.Frame.Height);
            }
        }
        protected override void UpdateCell(MyCollectionViewCell cell, int sec, int idx)
        {
            var data = cell.data as MyCellData;
            var sd = sections[sec];
            var type = sd.insertViewIndex == -1 ? "data" : "insert";
            if (sd.IsInsertView())
            {
                // logger.Log("update iv cell", sec, sd.insertViewIndex);
                cell.BackgroundColor = UIColor.Yellow;
                data.labTitle.Text = $"{type}:{sd.insertViewIndex}, stick:{sd.insertView.Superview!=cell}";
            }
            else
            {
                cell.BackgroundColor = UIColor.Red.ColorWithAlpha(0.8f);
                data.labTitle.Text = $"{type}, ip:{sec}.{idx}, data:{sd.dataStartIndex+idx}";
            }
        }
        protected override int GetItemsCount(int sec)
        {
            var sd = sections[sec];
            if (sd.insertViewIndex != -1)
                return 1;
            else
                return sd.dataCount;
        }

        protected override CGSize GetItemsSize(int sec, int idx)
        {
            var w = View.Bounds.Width;
            var sd = sections[sec];
            if (sd.IsInsertView())
            {
                return new CGSize(w, sd.insertViewHeight);
            }
            else
            {
                return new CGSize(w / 2 - 1, w / 2 - 1);
            }
        }

        protected override int GetSectionCount()
        {
            return sections?.Count??0;
        }

        protected(SectionData, MyCollectionViewCell) GetInsertViewCell(int idx)
        {
            int sec = -1;
            for (int i = 0; i < sections.Count; i++)
                if (sections[i].insertViewIndex == idx)
                {
                    sec = i;
                    break;
                }

            var fcp = NSIndexPath.FromItemSection(0, sec);
            return (sections[sec], listView.CellForItem(fcp) as MyCollectionViewCell);
        }

        protected CGRect GetInsertViewFrame(int idx)
        {
            int sec = -1;
            for (int i = 0; i < sections.Count; i++)
                if (sections[i].insertViewIndex == idx)
                {
                    sec = i;
                    break;
                }

            var fcp = NSIndexPath.FromItemSection(0, sec);
            var attr = listView.GetLayoutAttributesForItem(fcp);
            return attr.Frame;
        }

        public void Reload()
        {
            sections = new List<SectionData>();
            var ins = GetInsertIndex();

            if (ins.Length == 0)
            {
                sections.Add(new SectionData()
                {
                    sectionIndex = 0,
                        dataStartIndex = 0,
                        dataCount = dataSource.Count,
                        insertViewIndex = -1,
                });
                listView.SectionCount = 1;
                listView.RegisterClassForCell(typeof(MyCollectionViewCell), "Data");
            }
            else
            {
                int dsIndex = 0;
                int insertViewIndex = 0;
                int sectionIndex = 0;
                foreach (var i in ins)
                {
                    int dc = i - dsIndex;
                    //把这一节之前的数据节点做为一节
                    if (dc > 0)
                    {
                        sections.Add(new SectionData()
                        {
                            sectionIndex = sectionIndex++,
                                dataStartIndex = dsIndex,
                                dataCount = dc,
                                insertViewIndex = -1,
                        });
                    }

                    var insertItem = GetInsertViewConfig(insertViewIndex);
                    logger.Log("reload. insertview", insertViewIndex, insertItem.height, insertItem.stickyHeight);
                    sections.Add(new SectionData()
                    {
                        sectionIndex = sectionIndex++,
                            dataStartIndex = -1,
                            insertView = insertItem.view,
                            insertViewIndex = insertViewIndex++,
                            insertViewHeight = insertItem.height,
                            insertViewStickHeight = insertItem.stickyHeight,
                            insertViewStickOverwrite = insertItem.overwrite,
                    });
                    dsIndex += dc;
                }

                //最后一节数据
                int remain = dataSource.Count - dsIndex;
                if (remain > 0)
                {
                    sections.Add(new SectionData()
                    {
                        sectionIndex = sectionIndex++,
                            dataStartIndex = dsIndex,
                            dataCount = remain,
                            insertViewIndex = -1,
                    });
                }

                listView.SectionCount = sections.Count;
                for (var i = 0; i < ins.Length; i++)
                {
                    listView.RegisterClassForCell(typeof(MyCollectionViewCell), "InsertView" + i);
                }
                listView.RegisterClassForCell(typeof(MyCollectionViewCell), "Data");
            }

            listView.MyGetCell = (v, ip) =>
            {
                var sd = sections[ip.Section];
                var ct = sd.insertViewIndex != -1 ? "InsertView" + sd.insertViewIndex : "Data";
                var cell = v.DequeueReusableCell(ct, ip) as MyCollectionViewCell;
                if (cell.data == null)
                    InitCell(cell, ip.Section);

                UpdateCell(cell, ip.Section, (int) ip.Item);
                return cell;
            };
            listView.ReloadData();
        }
    }

    //使用视频信息做为数据源的可插入列表
    class VCExMovieList : VCBaseInsertableList<VideoItem>
    {
        protected class MovieCellData : MyCellData
        {
            public UIView cellView;
            public UIImageView imageView;
            public UILabel labName;
            public UILabel labViews;
            public UILabel labPraises;
            public MovieCellData(MyCollectionViewCell cell) : base(cell)
            {
                cellView = new UIView();
                cellView.SetParent(cell);
                cellView.Frame = new CGRect(10, 10, cell.Bounds.Width - 20, cell.Bounds.Height - 10);

                cellView.Layer.CornerRadius = 10;
                cellView.Layer.BorderWidth = 1;
                cellView.Layer.BorderColor = new CGColor(0.3f, 0.3f, 0.3f, 1f);
                cellView.ClipsToBounds = true;
                cellView.BackgroundColor = UIColor.White;

                imageView = new UIImageView();
                imageView.SetParent(cellView);
                imageView.Frame = new CGRect(0, 0, cellView.Bounds.Width, cellView.Bounds.Height * 0.7);

                int dx = 8;
                labName = new UILabel();
                labName.SetParent(cellView);
                labName.Frame = new CGRect(dx, imageView.Frame.Height, cellView.Frame.Width - 2 * dx, cellView.Frame.Height * 0.3);
                labName.TextColor = UIColor.FromRGB(93, 93, 93);
                labName.Font = UIFont.SystemFontOfSize(13);
                labName.AdjustsFontSizeToFitWidth = true;
                labName.LineBreakMode = UILineBreakMode.WordWrap;
                labName.Lines = 2;

                nfloat labelTop = imageView.Frame.Height - 22;

                var labelView = new UIView();
                labelView.SetParent(cellView);
                labelView.BackgroundColor = UIColor.Black;
                labelView.Alpha = 0.5f;
                labelView.Frame = new CGRect(0, labelTop, cellView.Bounds.Width, 22);

                var viewNumsImage = new UIImageView();
                viewNumsImage.SetParent(cellView);
                viewNumsImage.Frame = new CGRect(5, labelTop + 2, 16, 16);
                var viewNumsImageA = UIImage.FromFile($"{App.HotStorageRoot}/res/category/Bofang01.png");
                viewNumsImage.Image = new UIImage(viewNumsImageA.CGImage, 2, UIImageOrientation.Up);

                labViews = new UILabel();
                labViews.SetParent(cellView);
                labViews.Frame = new CGRect(viewNumsImage.Frame.Width + 10, labelTop, cellView.Bounds.Width / 2 - 30, 20);
                labViews.TextColor = UIColor.White;
                labViews.Font = UIFont.SystemFontOfSize(11);

                labPraises = new UILabel();
                labPraises.SetParent(cellView);
                labPraises.Frame = new CGRect(cellView.Bounds.Width / 2, labelTop, cellView.Bounds.Width / 2 - 25, 20);
                labPraises.TextAlignment = UITextAlignment.Right;
                labPraises.TextColor = UIColor.White;
                labPraises.Font = UIFont.SystemFontOfSize(11);

                var fabulousImage = new UIImageView();
                fabulousImage.SetParent(cellView);
                fabulousImage.Frame = new CGRect(cellView.Bounds.Width - 20, labelTop + 2, 16, 16);
                var fabulousImageA = UIImage.FromFile($"{App.HotStorageRoot}/res/category/Dianzan01.png");
                fabulousImage.Image = new UIImage(fabulousImageA.CGImage, 2, UIImageOrientation.Up);

                // imageView = new UIImageView();
                // imageView.SetParent(cell);
                // imageView.Frame = new CGRect(0, 0, cell.Bounds.Width, cell.Bounds.Height);
            }
        }
        protected override MyCellData CreateCellData(MyCollectionViewCell cell, SectionData sd)
        {
            return new MovieCellData(cell);
        }

        protected override void UpdateCell(MyCollectionViewCell cell, int sec, int idx)
        {
            // base.UpdateCell(cell, sec, idx);
            var cd = cell.data as MovieCellData;
            var sd = sections[sec];
            cd.cellView.Hidden = sd.IsInsertView();
            if (!sd.IsInsertView())
            {
                var vi = dataSource[sd.dataStartIndex + idx];
                cd.labName.Text = vi.vname;
                cd.labViews.Text = vi.views + "";
                // logger.Log("vi.views:------>" + vi.views);
                cd.labPraises.Text = vi.praises + "";
                mb.iOS.Util.SetUIImageViewUrl(cd.imageView, vi.vpic);
            }
        }
        protected override void OnItemSelected(int sec, int idx)
        {
            var sd = sections[sec];
            logger.Log("click movie", sec, idx, sd.dataStartIndex);
            var data = dataSource[sd.dataStartIndex + idx];
            AppDelegate.Instance.NavController.PushViewController(new VCMoviePlayer(data), false);
        }
    }
}